﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;

namespace ExpressionMapper
{
    using MappingExpressionGenerator = Func<Expression, Type, Expression,ParameterExpression, Expression>;

    public static partial class Generators
    {
        /// <summary>
        /// Returns generator for array to array mappings.
        /// </summary>
        public static MappingExpressionGenerator ArrayToArray()
        {
            return (fromExpr, to, customMapping, referenceDictionary) =>
                   (fromExpr.Type.IsArray && to.IsArray)
                       ? customMapping ?? GenerateArraConversionExpression(fromExpr, to, referenceDictionary)
                       : null;
        }

        private static Expression GenerateArraConversionExpression( Expression fromExpr,
                                                                  Type to, ParameterExpression referenceDictionary)
        {
            Debug.WriteLine(string.Format("\tArrayToArray ({0}): {1} to {2}", fromExpr.NodeType, fromExpr.Type.Name, to.Name));

            Type fromElementType = fromExpr.Type.GetElementType();
            Type toElementType = to.GetElementType();
    
            MethodInfo convertAllMethod = typeof (Generators)
                .GetMethod("ConvertArray", BindingFlags.Static | BindingFlags.Public)
                .MakeGenericMethod(fromElementType, toElementType);

            return Expression.Call(convertAllMethod, fromExpr, referenceDictionary);
        }

        public static TOutput[] ConvertArray<TInput, TOutput>(TInput[] input, ReferenceDictionary referenceDictionary)
        {
            if (input == null)
                return null;

            var result = new TOutput[input.Length];
            for (int i = 0; i < input.Length; i++)
            {
                result[i] = Mapper.Map<TInput, TOutput>(input[i], referenceDictionary);
            }
            return result;
        }
    }
}